#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <error.h>
#include <string.h>
#include "ping_interface_common.h"
#include <pthread.h>

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>


#define SERVER_PORT 9999


struct recv_msg{
	int msg_id;
	int pack_num;
	char devices[20];
	char url[64];
};

/*
static void sleep_ms(unsigned int secs)
{

    struct timeval tval;

    tval.tv_sec=secs/1000;

    tval.tv_usec=(secs*1000)%1000000;

    select(0,NULL,NULL,NULL,&tval);

}
*/

struct thread_runtime {
	int 								running;
	int									socketfd;
	ping_configuration_packet* 			pconf;
	struct send_msg*					psend_msg;
	struct recv_msg*					precv_msg;
};



static void split(char *src,const char *separator,char **dest,int *num) {
	/*
		src 源字符串的首地址(buf的地址) 
		separator 指定的分割字符
		dest 接收子字符串的数组
		num 分割后子字符串的个数
	*/
     char *pNext;
     int count = 0;
     if (src == NULL || strlen(src) == 0) //如果传入的地址为空或长度为0，直接终止 
        return;
     if (separator == NULL || strlen(separator) == 0) //如未指定分割的字符串，直接终止 
        return;
     pNext = (char *)strtok(src,separator); //必须使用(char *)进行强制类型转换(虽然不写有的编译器中不会出现指针错误)
     while(pNext != NULL) {
          *dest++ = pNext;
          ++count;
         pNext = (char *)strtok(NULL,separator);  //必须使用(char *)进行强制类型转换
    }  
    *num = count;
} 




static int recv_msg_parse(char* recv_buf, struct recv_msg* out_msg){
	char *revbuf[8] = {0};
	int all_num = 0;
	split(recv_buf, ",", revbuf, &all_num); //调用函数进行分割 
	for(int i = 0;i < all_num; i ++) {
		//lr_output_message("%s\n",revbuf[i]);
		char *cmdbuf[2];
		int num = 0;
		split(revbuf[i], "-", cmdbuf, &num);
		if (!strcmp(cmdbuf[0], "id")){
			out_msg->msg_id = atoi(cmdbuf[1]);
			printf("msg->msg_id : %d\n", out_msg->msg_id);
		} else if (!strcmp(cmdbuf[0], "num")){
			out_msg->pack_num = atoi(cmdbuf[1]);
			printf("msg->pack_num : %d\n", out_msg->pack_num);
		} else if (!strcmp(cmdbuf[0], "devices")){
			strncpy(out_msg->devices, cmdbuf[1], strlen(cmdbuf[1]));
			out_msg->devices[strlen(cmdbuf[1])] = '\0';
			//out_msg->devices = atoi(cmdbuf[1]);
			printf("msg->devices : %s\n", out_msg->devices);
		} else if (!strcmp(cmdbuf[0], "url")){
			strncpy(out_msg->url, cmdbuf[1], strlen(cmdbuf[1]));
			out_msg->url[strlen(cmdbuf[1])] = '\0';
			printf("msg->url : %s\n", out_msg->url);
		}
	}
	return 0;
}

static int msg_combination(char* out_buf, struct send_msg* msg)
{
	sprintf(out_buf, "id-%d,entity-%s,target-%s|", msg->msg_id, msg->entity, msg->target);
//	__log_error("out_buf = %s\n", out_buf);
	return 0;
}


static int send_finsh(int	socketfd, char* target)
{
	char send_buf[256];
	memset(send_buf, 0, sizeof(send_buf));
	sprintf(send_buf, "id-333,entity-finsh,target-%s|", target);
	int send_result = send(socketfd, send_buf, strlen(send_buf)+1, 0);
	if (send_result < 0) {
		extern int errno;
		__log_error("get error %s", strerror(errno));
		return -1;
	}
	return 0;
}



static void* func(void* p)
{
	int send_result = 0;
	char send_buf[256];
	__log_debug("\n");
	struct handle_send_msg* phmsg= (struct handle_send_msg *)p;
	memset(send_buf, 0, sizeof(send_buf));
	
	msg_combination(send_buf, &phmsg->msg);
	__log_error("send_buf = %s\n", send_buf);
	send_result = send(phmsg->socketfd, send_buf, strlen(send_buf)+1, 0);
	if (send_result < 0) {
		extern int errno;
		__log_error("get error %s", strerror(errno));
	}
    return NULL;
}

static ping_configuration_packet* g_conf_9607 = NULL;
static ping_configuration_packet* g_conf_660 = NULL;
//static struct thread_runtime rt_660, rt_9607;


static void *fun_ping(void *arg)
{
	struct handle_send_msg* phmsg = (struct handle_send_msg*)arg;
	struct handle_send_msg smsg;
	memcpy(&smsg, phmsg, sizeof(struct handle_send_msg));
	__log_debug("I'm thread, Thread ID = %lu\n", pthread_self());

	st_handler_packet handler = {
		.handler_func = func,
		.arg = (void *)&smsg
	};
	if (!strcmp(smsg.msg.target, "660")) {	
		do_ping(g_conf_660, &handler);
		__log_debug();
	} else if(!strcmp(smsg.msg.target, "9607")){
		do_ping(g_conf_9607, &handler);
		__log_debug();
	}
	__log_debug("target = %s\n", smsg.msg.target);
	send_finsh(smsg.socketfd, smsg.msg.target);
	__log_debug("\n");
	pthread_exit(NULL);
}




static int  recv_handle(int connect_fd, struct recv_msg* msg) 
{
#if 0
	static struct recv_msg rmsg_660;	
	static struct recv_msg rmsg_9607;	
	switch (msg->devices)
	{	
		case 660:
		{
			memcpy(&rmsg_660, msg, sizeof(struct recv_msg));
			rt_660.running = 1;
			__log_debug("rt_660.running = %d\n", rt_660.running);
			rt_660.precv_msg = &rmsg_660;
			__log_debug("id = %d, num = %d, url = %s, devices = %d\n",
				rt_660.precv_msg->msg_id, rt_660.precv_msg->pack_num, 
				rt_660.precv_msg->url,rt_660.precv_msg->devices);
			rt_660.socketfd = connect_fd;
			break;
		}
		case 9607:
		{
	//		__log_debug("\n");
			memcpy(&rmsg_9607, msg, sizeof(struct recv_msg));
			rt_9607.running = 1;
			__log_debug("rt_9607.running = %d\n", rt_9607.running);
			rt_9607.precv_msg = &rmsg_9607;
			rt_9607.socketfd = connect_fd;

#if 0			
			__log_debug("id = %d, num = %d, url = %s, devices = %d\n",
				rt_9607.precv_msg->msg_id, rt_9607.precv_msg->pack_num, 
				rt_9607.precv_msg->url,rt_9607.precv_msg->devices);
	
				__log_debug("id = %d, num = %d, url = %s, devices = %d\n",
				rmsg_660.msg_id, rmsg_660.pack_num, 
				rmsg_660.url,rmsg_660.devices);
#endif
			break;
		}
		
		default:
			printf("[%s][%d] unkown cmd\n", __func__, __LINE__);	
			break;
	}

#else 
	char send_buf[128];	
	int send_result = 0;
	
	switch (msg->msg_id)
	{
		//ping_set
		case 111:
		{
			if (!strncmp(msg->devices, "660", strlen(msg->devices))) {	
				if (g_conf_660 == NULL) {
					g_conf_660 = (ping_configuration_packet *)malloc(sizeof(ping_configuration_packet));
					if (g_conf_660 == NULL) {
						__log_error("ping: out of memory.\n");
						sprintf(send_buf, "id-111,entity-out of memory,target-%s|", msg->devices);
					}
					g_conf_660->npackets = msg->pack_num;
					g_conf_660->url = msg->url;
					g_conf_660->device = "rmnet_data2";
				}
				int ret = ping_set(g_conf_660);
				if (ret) {
					sprintf(send_buf, "id-111,entity-no,target-%s|", msg->devices);
					__log_error("ping_set failed\n");
					//return -1;
				} else {
					sprintf(send_buf, "id-111,entity-yes,target-%s|", msg->devices);
				}
					
				send_result = send(connect_fd, send_buf, strlen(send_buf)+1, 0);
				if (send_result < 0) {
					extern int errno;
					__log_error("get error %s", strerror(errno));
				}
	
				printf("[%s][%d] ping_set end. send_result = %d\n", __func__, __LINE__, send_result);	
			}else if (!strncmp(msg->devices, "9607", strlen(msg->devices))) {
				if (g_conf_9607 == NULL) {
					g_conf_9607 = (ping_configuration_packet *)malloc(sizeof(ping_configuration_packet));
					if (g_conf_9607 == NULL) {
						__log_error("ping: out of memory.\n");
						sprintf(send_buf, "id-111,entity-out of memory,target-%s|", msg->devices);
					}
					g_conf_9607->npackets = msg->pack_num;
					g_conf_9607->url = msg->url;
					g_conf_9607->device = "ppp0";
				}
				int ret = ping_set(g_conf_9607);
				if (ret) {
					sprintf(send_buf, "id-111,entity-no,target-%s|", msg->devices);
					__log_error("ping_set failed\n");
					//return -1;
				} else {
					sprintf(send_buf, "id-111,entity-yes,target-%s|", msg->devices);
				}
					
				send_result = send(connect_fd, send_buf, strlen(send_buf)+1, 0);
				if (send_result < 0) {
					extern int errno;
					__log_error("get error %s", strerror(errno));
				}	
			}else {
					
			}
			break;
		}
		//do_ping
		case 222:
			{	
				__log_debug("\n");

				struct handle_send_msg smsg;
				smsg.socketfd = connect_fd;
				smsg.msg.msg_id = msg->msg_id;
				//smsg.msg.target = msg->devices;

				if (!strncmp(msg->devices, "660", strlen(msg->devices))) {	
					g_conf_660->npackets = msg->pack_num;
					g_conf_660->device = "rmnet_data2";
					g_conf_660->url = msg->url;
					smsg.msg.target = "660";
				}else if (!strncmp(msg->devices, "9607", strlen(msg->devices))) {
					g_conf_9607->npackets = msg->pack_num;
					g_conf_9607->device = "ppp0";
					g_conf_9607->url = msg->url;
					smsg.msg.target = "9607";
				}else {

				}
				
				
				#if 1
				pthread_t thread_id;
				pthread_attr_t  attr;
				pthread_attr_init(&attr);
				pthread_attr_setdetachstate(&attr,  PTHREAD_CREATE_DETACHED);
				int ret = pthread_create(&thread_id, &attr ,fun_ping, (void*)&smsg); // 成功返回0，错误返回错误编号
				#else
				int ret = pthread_create(&thread_id, NULL ,fun_ping, (void*)&smsg); // 成功返回0，错误返回错误编号
				#endif
				if(ret) {
					__log_error("Create pthread error!\n");
					break;
				}
					
				
	
#if 0
	
					int do_ping(ping_configuration_packet* pst_ping_config, st_handler_packet* phandler)	
					char ping_buf[256] = "id-222,entity-helloworld,target-9607|";
					send_result = send(connect_fd, ping_buf, strlen(ping_buf)+1, 0);	
					if (send_result < 0) {
						extern int errno;
						printf("get error %s", strerror(errno));
	
					}
					printf("[%s][%d] ping_set end. send_result = %d\n", __func__, __LINE__, send_result);
#endif
			}
			break;
		
		//ping_set
		case 333:
			{
				char ping_buf[256] = "id-333,entity-yes,target-660|";
				send_result = send(connect_fd, ping_buf, strlen(ping_buf)+1, 0);	
				if (send_result < 0) {
					extern int errno;
					printf("get error %s", strerror(errno));
		
				}
				printf("[%s][%d] ping_set end. send_result = %d\n", __func__, __LINE__, send_result);	
			}
			break;
		
		default:
			printf("[%s][%d] unkown cmd %d\n", __func__, __LINE__, send_result);	
			break;
	}
	return 0;
#endif
}

#if 0
static int	recv_msg_handle(struct thread_runtime* prt) 
{
	struct recv_msg* msg = prt->precv_msg;
	ping_configuration_packet* p_conf = prt->pconf;
	char send_buf[128];	
	int send_result = 0;
	__log_debug("\n");
	switch (msg->msg_id)
		{
			//ping_set
			case 111:
				{
					__log_debug("\n");	
					if (p_conf == NULL) {
						p_conf = (ping_configuration_packet *)malloc(sizeof(ping_configuration_packet));
						if (p_conf == NULL) {
							__log_error("ping: out of memory.\n");
							sprintf(send_buf, "id-111,entity-out of memory,target-%d|", msg->devices);
						}
						p_conf->npackets = msg->pack_num;
						
						p_conf->url = msg->url;
						if (msg->devices == 660)
							p_conf->device = "rmnet_data0";
						else if (msg->devices == 9607)
							p_conf->device = "ppp0";
					}
					int ret = ping_set(p_conf);
					if (ret) {
						sprintf(send_buf, "id-111,entity-no,target-%d|", msg->devices);
						__log_error("ping_set failed\n");
						//return -1;
					} else {
						sprintf(send_buf, "id-111,entity-yes,target-%d|", msg->devices);
					}
					return 0;
						
					send_result = send(prt->socketfd, send_buf, strlen(send_buf)+1, 0);
					if (send_result < 0) {
						extern int errno;
						__log_error("get error %s", strerror(errno));
					}
	
					printf("[%s][%d] ping_set end. send_result = %d\n", __func__, __LINE__, send_result);	
				}
				break;
	
			//do_ping
			case 222:
				{	
					__log_debug("\n");
					p_conf->npackets = msg->pack_num;
					if (msg->devices == 660)
						p_conf->device = "rmnet_data0";
					else if (msg->devices == 9607)
						p_conf->device = "ppp0";
					p_conf->url = msg->url;

					struct send_msg smsg;
					smsg.msg_id = 222;
					if (msg->devices == 660)
						smsg.target = "660";
					else if (msg->devices == 9607)
						smsg.target = "9607";
					prt->psend_msg = &smsg;
					//handler_660.arg = (void *)prt;
					st_handler_packet handler = {
						.handler_func = func,
						.arg = (void *)prt
					};
					__log_debug("\n");	
					do_ping(p_conf, &handler);
					__log_debug("\n");
					send_finsh(prt->socketfd, smsg.target);
					__log_debug("\n");
	
#if 0
	
					int do_ping(ping_configuration_packet* pst_ping_config, st_handler_packet* phandler)	
					char ping_buf[256] = "id-222,entity-helloworld,target-9607|";
					send_result = send(connect_fd, ping_buf, strlen(ping_buf)+1, 0);	
					if (send_result < 0) {
						extern int errno;
						printf("get error %s", strerror(errno));
	
					}
					printf("[%s][%d] ping_set end. send_result = %d\n", __func__, __LINE__, send_result);
#endif
				}
				break;
			
			//ping_set
			case 333:
				{
					char ping_buf[256] = "id-333,entity-yes,target-660|";
					send_result = send(prt->socketfd, ping_buf, strlen(ping_buf)+1, 0);	
					if (send_result < 0) {
						extern int errno;
						printf("get error %s", strerror(errno));
			
					}
					printf("[%s][%d] ping_set end. send_result = %d\n", __func__, __LINE__, send_result);	
				}
				break;
			
			default:
				printf("[%s][%d] unkown cmd %d\n", __func__, __LINE__, send_result);	
				break;
		}
		return 0;

}

#endif
#if 1


#if 0

static void *fun_660(void *arg)
{
	struct thread_runtime* prt = (struct thread_runtime *)arg; 
	__log_debug("I'm thread, Thread ID = %lu\n", pthread_self());
	while (1) {
		if (rt_660.running) {
			__log_debug("id = %d, num = %d, url = %s, devices = %d\n",
				rt_660.precv_msg->msg_id, rt_660.precv_msg->pack_num, 
				rt_660.precv_msg->url,rt_660.precv_msg->devices);
			recv_msg_handle(&rt_660);
			prt->running = 0;
			sleep_ms(100);
		}
	}
	__log_debug("\n");
}

static void *fun_9607(void *arg)
{
	struct thread_runtime* prt = (struct thread_runtime *)arg; 
	__log_debug("I'm thread, Thread ID = %lu\n", pthread_self());
	while (1) {
		if (prt->running) {
				__log_debug("id = %d, num = %d, url = %s, devices = %d\n",
				rt_9607.precv_msg->msg_id, rt_9607.precv_msg->pack_num, 
				rt_9607.precv_msg->url,rt_9607.precv_msg->devices);
			recv_msg_handle(&rt_9607);
			prt->running = 0;
			sleep_ms(100);
		}	
	}
	__log_debug("\n");
}

#endif

int main()
{
//	uid_t uid = 0;
//    gid_t gid = 0;
	
//	if (setgid(gid)) fprintf(stderr, "[%s][%d]setgid err\n", __func__, __LINE__);
//    if (setuid(uid)) fprintf(stderr, "[%s][%d]setuid err\n", __func__, __LINE__);
	
	printf("[%s][%d]getgid = %d\n", __func__, __LINE__, getgid());
	printf("[%s][%d]getuid = %d\n", __func__, __LINE__, getuid());
	/*
	//pthread_t id_660, id_9607;
	//rt_660.pconf = g_conf_660;
	//rt_9607.pconf = g_conf_9607;
	
	
	int ret = pthread_create(&id_660, NULL ,fun_660, (void *)&rt_660); // 成功返回0，错误返回错误编号
	if(ret) {
		__log_error("Create pthread error!\n");
		exit (1);
	}
	
	ret = pthread_create(&id_9607, NULL ,fun_9607, (void *)&rt_9607); // 成功返回0，错误返回错误编号
	if(ret) {
		__log_error("Create pthread error!\n");
		exit (1);
	}
	*/
	

    //创建一个socket
    int listen_fd = socket(AF_INET,SOCK_STREAM,0);
        
    //配置ip port 协议
    struct sockaddr_in addrSrc,addrClient;
    bzero(&addrSrc, sizeof(addrSrc));
	bzero(&addrClient, sizeof(addrClient));
   
    addrSrc.sin_family=AF_INET;
    addrSrc.sin_port=htons(SERVER_PORT);
    addrSrc.sin_addr.s_addr=INADDR_ANY;

	char buffer[128];
        
    //绑定
    bind(listen_fd,(struct sockaddr*)&addrSrc,sizeof(struct sockaddr_in));
 
    //监听
    listen(listen_fd,5);
    
    while(1)
    {
        int connect_fd = 0;
		//int send_result = 0;
        int len = sizeof(struct sockaddr_in);
		printf("[%s][%d]listen ....\n", __func__, __LINE__);	
        connect_fd = accept(listen_fd, (struct sockaddr*)&addrClient, (socklen_t *)&len);
		if (connect_fd < 0){
        	if (errno == EINTR)
            	continue;
        	else
            	__log_error("accept error");
    	}
		while (1) {
			struct recv_msg recv_msg;
			memset((void*)buffer, '\0', sizeof(buffer));
			int iDataNum = recv(connect_fd, buffer, 128, 0);
        	if (iDataNum < 0) {
				 if (errno == EINTR) {
            		continue;
				 } else if (errno == EBADF) {
					close(connect_fd);
					break;
				 } else {
            		//printf("accept error");
          	   		perror("recv null");
				 }
				 	
        	   continue;
       		} else if (iDataNum == 0) {
				printf("[%s][%d] breakup; \n", __func__, __LINE__);
				close(connect_fd);
				break;
			}
			buffer[iDataNum] = '\0';
			printf("[%s][%d]recv cmd:%s, length : %d\n", __func__, __LINE__, buffer, iDataNum);
			recv_msg_parse(buffer, &recv_msg);
			
			recv_handle(connect_fd, &recv_msg);
			__log_debug();
			memset((void*)&recv_msg, '\0', sizeof(recv_msg));
			if (strcmp(buffer, "quit") == 0)
                break;					
			
        }
	
    }    
    return 0;
}

#else

static int flag = 0;

static void *fun_660(void *arg)
{
	struct thread_runtime* prt = (struct thread_runtime *)arg; 
	struct handle_send_msg*	phandle_msg = prt->phandle_msg;
	
	__log_debug("I'm thread, Thread ID = %lu\n", pthread_self());
	while (1) {
		if (prt->running) {
			recv_msg_handle(phandle_msg->socketfd , &phandle_msg->msg);
			prt->running = 0;
		}
	}

}

static void *fun_9607(void *arg)
{
	struct thread_runtime* prt = (struct thread_runtime *)arg; 
	struct handle_send_msg*	phandle_msg = prt->phandle_msg;
	__log_debug("I'm thread, Thread ID = %lu\n", pthread_self());
	while (1) {
		if (prt->running) {
			recv_msg_handle(phandle_msg->socketfd , &phandle_msg->msg);
			prt->running = 0;
		}
	}
}


int main()
{
	pthread_t id_660, id_9607;
	struct thread_runtime rt_660, rt_9607;
	rt_660.pconf = &g_conf_660;
	rt_9607.pconf = &g_conf_9607;
	
	int ret = pthread_create(&id_660,NULL,fun_660, (void *)&rt_660); // 成功返回0，错误返回错误编号
　　if(ret) {
　　　　__log_error("Create pthread error!\n");
　　　　exit (1);
　　}

	ret = pthread_create(&id_9607,NULL,fun_9607, (void *)&rt_9607); // 成功返回0，错误返回错误编号
	if(ret) {
		__log_error("Create pthread error!\n");
	　　exit (1);
	}


	
	if (0) {
		struct msg recv_msg;
		recv_msg_parse(ping_buf, &recv_msg);
		recv_msg_handle(8, &recv_msg);
	}


	while(1) {
		flag = !flag;
		sleep(2);
	}
}


#endif

